Asyncio സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവുകളെക്കുറിച്ചുള്ള സമഗ്രമായ ഗൈഡ്: ലോക്കുകൾ, സെമാഫോറുകൾ, ഇവന്റുകൾ. Python-ൽ കൺകറന്റ് പ്രോഗ്രാമിംഗിനായി അവ എങ്ങനെ ഫലപ്രദമായി ഉപയോഗിക്കാമെന്ന് മനസിലാക്കുക.
Asyncio സിൻക്രണൈസേഷൻ: ലോക്കുകൾ, സെമാഫോറുകൾ, ഇവന്റുകൾ എന്നിവയിൽ പ്രാവീണ്യം നേടുക
Python-ലെ അസിൻക്രണസ് പ്രോഗ്രാമിംഗ്, asyncio
ലൈബ്രറി നൽകുന്ന പിന്തുണയോടെ, കാര്യക്ഷമമായി കൺകറന്റ് പ്രവർത്തനങ്ങൾ കൈകാര്യം ചെയ്യുന്നതിനുള്ള ശക്തമായ മാതൃക നൽകുന്നു. എന്നിരുന്നാലും, ഒന്നിലധികം കോറൂട്ടിനുകൾ ഒരേ സമയം പങ്കിട്ട ഉറവിടങ്ങൾ ഉപയോഗിക്കുമ്പോൾ, റേസ് കണ്ടീഷനുകൾ തടയുന്നതിനും ഡാറ്റാ സമഗ്രത ഉറപ്പാക്കുന്നതിനും സിൻക്രണൈസേഷൻ നിർണായകമാണ്. ഈ സമഗ്രമായ ഗൈഡ് asyncio
നൽകുന്ന അടിസ്ഥാന സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവുകൾ പര്യവേക്ഷണം ചെയ്യുന്നു: ലോക്കുകൾ, സെമാഫോറുകൾ, ഇവന്റുകൾ.
സിൻക്രണൈസേഷന്റെ ആവശ്യകത മനസ്സിലാക്കുക
ഒരു സിൻക്രണസ്, സിംഗിൾ-ത്രെഡഡ് എൻവയോൺമെന്റിൽ, പ്രവർത്തനങ്ങൾ തുടർച്ചയായി നടപ്പിലാക്കുന്നു, ഇത് ഉറവിട മാനേജ്മെൻ്റ് ലളിതമാക്കുന്നു. എന്നാൽ അസിൻക്രണസ് എൻവയോൺമെൻ്റുകളിൽ, ഒന്നിലധികം കോറൂട്ടിനുകൾക്ക് ഒരേസമയം പ്രവർത്തിക്കാനും അവയുടെ എക്സിക്യൂഷൻ പാതകൾക്ക് തടസ്സമുണ്ടാകാനും സാധ്യതയുണ്ട്. ഈ കൺകറൻസി റേസ് കണ്ടീഷനുകൾക്കുള്ള സാധ്യത വർദ്ധിപ്പിക്കുന്നു, ഇവിടെ ഒരു പ്രവർത്തനത്തിൻ്റെ ഫലം കോറൂട്ടിനുകൾ പങ്കിട്ട ഉറവിടങ്ങൾ ആക്സസ് ചെയ്യുകയും പരിഷ്കരിക്കുകയും ചെയ്യുന്ന ക്രമത്തെ ആശ്രയിച്ചിരിക്കുന്നു.
ഒരു ലളിതമായ ഉദാഹരണം പരിഗണിക്കുക: രണ്ട് കോറൂട്ടിനുകൾ ഒരു പൊതുവായ കൗണ്ടർ വർദ്ധിപ്പിക്കാൻ ശ്രമിക്കുന്നു. ശരിയായ സിൻക്രണൈസേഷൻ ഇല്ലാതെ, രണ്ട് കോറൂട്ടിനുകളും ഒരേ മൂല്യം വായിക്കുകയും അത് പ്രാദേശികമായി വർദ്ധിപ്പിക്കുകയും തുടർന്ന് ഫലം തിരികെ എഴുതുകയും ചെയ്തേക്കാം. ഒരു ഇൻക്രിമെൻ്റ് നഷ്ടപ്പെടുന്നതിനാൽ, അന്തിമ കൗണ്ടർ മൂല്യം തെറ്റായിരിക്കാം.
പങ്കിട്ട ഉറവിടങ്ങളിലേക്കുള്ള ആക്സസ് ഏകോപിപ്പിക്കുന്നതിനുള്ള സംവിധാനങ്ങൾ സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവുകൾ നൽകുന്നു, ഒരു സമയം ഒരു കോറൂട്ടിന് മാത്രമേ കോഡിന്റെ നിർണായക ഭാഗത്തേക്ക് പ്രവേശിക്കാൻ കഴിയൂ അല്ലെങ്കിൽ ഒരു കോറൂട്ടിൻ മുന്നോട്ട് പോകുന്നതിന് മുമ്പ് ചില പ്രത്യേക നിബന്ധനകൾ പാലിക്കണം എന്ന് ഉറപ്പാക്കുന്നു.
Asyncio ലോക്കുകൾ
ഒരു asyncio.Lock
എന്നത് ഒരു മ്യൂച്വൽ എക്സ്ക്ലൂഷൻ ലോക്ക് (mutex) ആയി പ്രവർത്തിക്കുന്ന ഒരു അടിസ്ഥാന സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവ് ആണ്. ഇത് ഒരു സമയം ഒരു കോറൂട്ടിന് മാത്രമേ ലോക്ക് നേടാൻ അനുവദിക്കൂ, ലോക്ക് റിലീസ് ചെയ്യുന്നതുവരെ മറ്റ് കോറൂട്ടിനുകളെ പരിരക്ഷിത ഉറവിടത്തിലേക്ക് പ്രവേശിക്കുന്നതിൽ നിന്ന് തടയുന്നു.
ലോക്കുകൾ എങ്ങനെ പ്രവർത്തിക്കുന്നു
ഒരു ലോക്കിന് രണ്ട് അവസ്ഥകളുണ്ട്: ലോക്ക് ചെയ്തതും അൺലോക്ക് ചെയ്തതും. ഒരു കോറൂട്ടിൻ ലോക്ക് നേടാൻ ശ്രമിക്കുന്നു. ലോക്ക് അൺലോക്ക് ആണെങ്കിൽ, കോറൂട്ടിൻ അത് ഉടൻ നേടുകയും മുന്നോട്ട് പോകുകയും ചെയ്യുന്നു. മറ്റൊരു കോറൂട്ടിൻ ലോക്ക് ചെയ്താൽ, നിലവിലെ കോറൂട്ടിൻ്റെ എക്സിക്യൂഷൻ താൽക്കാലികമായി നിർത്തിവയ്ക്കുകയും ലോക്ക് ലഭ്യമാകുന്നതുവരെ കാത്തിരിക്കുകയും ചെയ്യുന്നു. ഉടമസ്ഥതയിലുള്ള കോറൂട്ടിൻ ലോക്ക് റിലീസ് ചെയ്തുകഴിഞ്ഞാൽ, കാത്തിരിക്കുന്ന കോറൂട്ടിനുകളിൽ ഒന്നിനെ ഉണർത്തി ആക്സസ് അനുവദിക്കുന്നു.
Asyncio ലോക്കുകൾ ഉപയോഗിക്കുന്നു
ഒരു asyncio.Lock
ഉപയോഗിക്കുന്നതിനുള്ള ഒരു ലളിതമായ ഉദാഹരണം ഇതാ:
import asyncio
async def safe_increment(lock, counter):
async with lock:
# Critical section: only one coroutine can execute this at a time
current_value = counter[0]
await asyncio.sleep(0.01) # Simulate some work
counter[0] = current_value + 1
async def main():
lock = asyncio.Lock()
counter = [0]
tasks = [safe_increment(lock, counter) for _ in range(10)]
await asyncio.gather(*tasks)
print(f"Final counter value: {counter[0]}")
if __name__ == "__main__":
asyncio.run(main())
ഈ ഉദാഹരണത്തിൽ, പങ്കിട്ട counter
ആക്സസ് ചെയ്യുന്നതിന് മുമ്പ് safe_increment
ലോക്ക് നേടുന്നു. async with lock:
എന്നത് ഒരു കോൺടെക്സ്റ്റ് മാനേജരാണ്. ഇത് ബ്ലോക്കിലേക്ക് പ്രവേശിക്കുമ്പോൾ സ്വയമേവ ലോക്ക് നേടുകയും എക്സെപ്ഷനുകൾ സംഭവിച്ചാലും പുറത്തുകടക്കുമ്പോൾ അത് റിലീസ് ചെയ്യുകയും ചെയ്യുന്നു. ഇത് നിർണായക വിഭാഗം എപ്പോഴും സംരക്ഷിക്കപ്പെടുന്നു എന്ന് ഉറപ്പാക്കുന്നു.
ലോക്ക് രീതികൾ
acquire()
: ലോക്ക് നേടാൻ ശ്രമിക്കുന്നു. ലോക്ക് ഇതിനകം ലോക്ക് ആണെങ്കിൽ, അത് റിലീസ് ചെയ്യുന്നതുവരെ കോറൂട്ടിൻ കാത്തിരിക്കും. ലോക്ക് നേടിയാൽTrue
നൽകുന്നു, അല്ലെങ്കിൽFalse
(ഒരു ടൈംഔട്ട് വ്യക്തമാക്കിയിട്ടുണ്ടെങ്കിൽ ടൈംഔട്ടിനുള്ളിൽ ലോക്ക് നേടാൻ കഴിഞ്ഞില്ലെങ്കിൽ).release()
: ലോക്ക് റിലീസ് ചെയ്യുന്നു. ലോക്ക് റിലീസ് ചെയ്യാൻ ശ്രമിക്കുന്ന കോറൂട്ടിൻ നിലവിൽ ലോക്ക് കൈവശം വെച്ചിട്ടില്ലെങ്കിൽ ഒരുRuntimeError
ഉയർത്തുന്നു.locked()
: ഏതെങ്കിലും കോറൂട്ടിൻ നിലവിൽ ലോക്ക് കൈവശം വെച്ചിട്ടുണ്ടെങ്കിൽTrue
നൽകുന്നു, അല്ലെങ്കിൽFalse
.
പ്രായോഗിക ലോക്ക് ഉദാഹരണം: ഡാറ്റാബേസ് ആക്സസ്
ഒരു അസിൻക്രണസ് എൻവയോൺമെൻ്റിൽ ഡാറ്റാബേസ് ആക്സസ് കൈകാര്യം ചെയ്യുമ്പോൾ ലോക്കുകൾ പ്രത്യേകിച്ചും ഉപയോഗപ്രദമാണ്. ഒന്നിലധികം കോറൂട്ടിനുകൾ ഒരേ സമയം ഒരേ ഡാറ്റാബേസ് ടേബിളിലേക്ക് എഴുതാൻ ശ്രമിച്ചേക്കാം, ഇത് ഡാറ്റാ കേടുപാടുകൾക്കോ സ്ഥിരതയില്ലാത്തതിനോ കാരണമാകുന്നു. ഈ എഴുത്ത് പ്രവർത്തനങ്ങൾ സീരിയലൈസ് ചെയ്യാൻ ഒരു ലോക്ക് ഉപയോഗിക്കാം, ഒരു സമയം ഒരു കോറൂട്ടിൻ മാത്രമേ ഡാറ്റാബേസ് പരിഷ്കരിക്കുന്നുള്ളൂ എന്ന് ഉറപ്പാക്കുന്നു.
ഉദാഹരണത്തിന്, ഒന്നിലധികം ഉപയോക്താക്കൾ ഒരേസമയം ഒരു ഉൽപ്പന്നത്തിൻ്റെ ഇൻവെൻ്ററി അപ്ഡേറ്റ് ചെയ്യാൻ ശ്രമിക്കുന്ന ഒരു ഇ-കൊമേഴ്സ് ആപ്ലിക്കേഷൻ പരിഗണിക്കുക. ഒരു ലോക്ക് ഉപയോഗിച്ച്, ഇൻവെൻ്ററി ശരിയായി അപ്ഡേറ്റ് ചെയ്യുന്നുവെന്ന് നിങ്ങൾക്ക് ഉറപ്പാക്കാൻ കഴിയും, ഇത് അമിതമായി വിൽക്കുന്നത് തടയുന്നു. നിലവിലെ ഇൻവെൻ്ററി ലെവൽ വായിക്കുന്നതിന് മുമ്പ് ലോക്ക് നേടുകയും വാങ്ങിയ ഇനങ്ങളുടെ എണ്ണം കുറയ്ക്കുകയും തുടർന്ന് പുതിയ ഇൻവെൻ്ററി ലെവൽ ഉപയോഗിച്ച് ഡാറ്റാബേസ് അപ്ഡേറ്റ് ചെയ്ത ശേഷം റിലീസ് ചെയ്യുകയും ചെയ്യും. നെറ്റ്വർക്ക് ലേറ്റൻസി റേസ് കണ്ടീഷനുകൾ വർദ്ധിപ്പിക്കാൻ കഴിയുന്ന വിതരണം ചെയ്ത ഡാറ്റാബേസുകളോ ക്ലൗഡ് അധിഷ്ഠിത ഡാറ്റാബേസ് സേവനങ്ങളോ കൈകാര്യം ചെയ്യുമ്പോൾ ഇത് വളരെ നിർണായകമാണ്.
Asyncio സെമാഫോറുകൾ
ഒരു asyncio.Semaphore
ഒരു ലോക്കിനേക്കാൾ പൊതുവായ സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവ് ആണ്. ഇത് ലഭ്യമായ ഉറവിടങ്ങളുടെ എണ്ണത്തെ പ്രതിനിധീകരിക്കുന്ന ഒരു ആന്തരിക കൗണ്ടർ നിലനിർത്തുന്നു. കൗണ്ടർ കുറയ്ക്കാൻ കോറൂട്ടിനുകൾക്ക് ഒരു സെമാഫോർ നേടാനും കൗണ്ടർ വർദ്ധിപ്പിക്കാൻ അത് റിലീസ് ചെയ്യാനും കഴിയും. കൗണ്ടർ പൂജ്യത്തിൽ എത്തുമ്പോൾ, ഒന്നോ അതിലധികമോ കോറൂട്ടിനുകൾ അത് റിലീസ് ചെയ്യുന്നത് വരെ കൂടുതൽ കോറൂട്ടിനുകൾക്ക് സെമാഫോർ നേടാൻ കഴിയില്ല.
സെമാഫോറുകൾ എങ്ങനെ പ്രവർത്തിക്കുന്നു
ഒരു സെമാഫോറിന് ഒരു പ്രാരംഭ മൂല്യമുണ്ട്, ഇത് ഒരു ഉറവിടത്തിലേക്ക് അനുവദനീയമായ പരമാവധി എണ്ണം കൺകറന്റ് ആക്സസുകളെ പ്രതിനിധീകരിക്കുന്നു. ഒരു കോറൂട്ടിൻ acquire()
എന്ന് വിളിക്കുമ്പോൾ, സെമാഫോറിൻ്റെ കൗണ്ടർ കുറയുന്നു. കൗണ്ടർ പൂജ്യത്തേക്കാൾ കൂടുതലോ തുല്യമോ ആണെങ്കിൽ, കോറൂട്ടിൻ ഉടൻ തന്നെ മുന്നോട്ട് പോകുന്നു. കൗണ്ടർ നെഗറ്റീവ് ആണെങ്കിൽ, മറ്റൊരു കോറൂട്ടിൻ സെമാഫോർ റിലീസ് ചെയ്യുന്നതുവരെ കോറൂട്ടിൻ തടയുന്നു, കൗണ്ടർ വർദ്ധിപ്പിക്കുകയും കാത്തിരിക്കുന്ന കോറൂട്ടിനെ മുന്നോട്ട് പോകാൻ അനുവദിക്കുകയും ചെയ്യുന്നു. release()
രീതി കൗണ്ടർ വർദ്ധിപ്പിക്കുന്നു.
Asyncio സെമാഫോറുകൾ ഉപയോഗിക്കുന്നു
ഒരു asyncio.Semaphore
ഉപയോഗിക്കുന്നതിനുള്ള ഒരു ഉദാഹരണം ഇതാ:
import asyncio
async def worker(semaphore, worker_id):
async with semaphore:
print(f"Worker {worker_id} acquiring resource...")
await asyncio.sleep(1) # Simulate resource usage
print(f"Worker {worker_id} releasing resource...")
async def main():
semaphore = asyncio.Semaphore(3) # Allow up to 3 concurrent workers
tasks = [worker(semaphore, i) for i in range(5)]
await asyncio.gather(*tasks)
if __name__ == "__main__":
asyncio.run(main())
ഈ ഉദാഹരണത്തിൽ, Semaphore
3 എന്ന മൂല്യത്തിൽ ആരംഭിക്കുന്നു, ഇത് 3 വർക്കർമാർക്ക് വരെ ഒരേസമയം ഉറവിടം ആക്സസ് ചെയ്യാൻ അനുവദിക്കുന്നു. async with semaphore:
എന്നത് വർക്കർ ആരംഭിച്ച് കഴിയുമ്പോൾ സെമാഫോർ റിലീസ് ചെയ്യുന്നുവെന്ന് ഉറപ്പാക്കുന്നു, എക്സെപ്ഷനുകൾ സംഭവിച്ചാലും. ഇത് കൺകറന്റ് വർക്കർമാരുടെ എണ്ണം പരിമിതപ്പെടുത്തുകയും ഉറവിടങ്ങളുടെ കുറവ് തടയുകയും ചെയ്യുന്നു.
സെമാഫോർ രീതികൾ
acquire()
: ആന്തരിക കൗണ്ടർ ഒന്ന് കുറയ്ക്കുന്നു. കൗണ്ടർ നെഗറ്റീവ് അല്ലാത്തതാണെങ്കിൽ, കോറൂട്ടിൻ ഉടൻ തന്നെ മുന്നോട്ട് പോകുന്നു. അല്ലെങ്കിൽ, മറ്റൊരു കോറൂട്ടിൻ സെമാഫോർ റിലീസ് ചെയ്യുന്നതുവരെ കോറൂട്ടിൻ കാത്തിരിക്കുന്നു. സെമാഫോർ നേടിയാൽTrue
നൽകുന്നു, അല്ലെങ്കിൽFalse
(ഒരു ടൈംഔട്ട് വ്യക്തമാക്കിയിട്ടുണ്ടെങ്കിൽ ടൈംഔട്ടിനുള്ളിൽ സെമാഫോർ നേടാൻ കഴിഞ്ഞില്ലെങ്കിൽ).release()
: ആന്തരിക കൗണ്ടർ ഒന്ന് വർദ്ധിപ്പിക്കുന്നു, ഇത് കാത്തിരിക്കുന്ന ഒരു കോറൂട്ടിനെ ഉണർത്താൻ സാധ്യതയുണ്ട്.locked()
: സെമാഫോർ നിലവിൽ ലോക്ക് ചെയ്ത അവസ്ഥയിലാണെങ്കിൽ (കൗണ്ടർ പൂജ്യമോ നെഗറ്റീവോ ആണ്)True
നൽകുന്നു, അല്ലെങ്കിൽFalse
.value
: ആന്തരിക കൗണ്ടറിൻ്റെ നിലവിലെ മൂല്യം നൽകുന്ന ഒരു റീഡ്-ഒൺലി പ്രോപ്പർട്ടി.
പ്രായോഗിക സെമാഫോർ ഉദാഹരണം: നിരക്ക് പരിമിതപ്പെടുത്തൽ
നിരക്ക് പരിമിതപ്പെടുത്തൽ നടപ്പിലാക്കുന്നതിന് സെമാഫോറുകൾ വളരെ അനുയോജ്യമാണ്. ഒരു ബാഹ്യ API-യിലേക്ക് അഭ്യർത്ഥനകൾ നടത്തുന്ന ഒരു ആപ്ലിക്കേഷൻ സങ്കൽപ്പിക്കുക. API സെർവറിന് ഓവർലോഡ് ചെയ്യുന്നത് ഒഴിവാക്കാൻ, ഒരു യൂണിറ്റ് സമയത്തിൽ അയച്ച അഭ്യർത്ഥനകളുടെ എണ്ണം പരിമിതപ്പെടുത്തേണ്ടത് അത്യാവശ്യമാണ്. അഭ്യർത്ഥനകളുടെ നിരക്ക് നിയന്ത്രിക്കാൻ ഒരു സെമാഫോർ ഉപയോഗിക്കാം.
ഉദാഹരണത്തിന്, ഒരു സെക്കൻഡിൽ അനുവദനീയമായ പരമാവധി അഭ്യർത്ഥനകളുടെ എണ്ണം പ്രതിനിധീകരിക്കുന്ന ഒരു മൂല്യം ഉപയോഗിച്ച് ഒരു സെമാഫോർ ആരംഭിക്കാൻ കഴിയും. ഒരു അഭ്യർത്ഥന നടത്തുന്നതിന് മുമ്പ്, ഒരു കോറൂട്ടിൻ സെമാഫോർ നേടുന്നു. സെമാഫോർ ലഭ്യമാണെങ്കിൽ (കൗണ്ടർ പൂജ്യത്തേക്കാൾ കൂടുതലാണ്), അഭ്യർത്ഥന അയയ്ക്കുന്നു. സെമാഫോർ ലഭ്യമല്ലെങ്കിൽ (കൗണ്ടർ പൂജ്യമാണ്), മറ്റൊരു കോറൂട്ടിൻ സെമാഫോർ റിലീസ് ചെയ്യുന്നതുവരെ കോറൂട്ടിൻ കാത്തിരിക്കുന്നു. ലഭ്യമായ അഭ്യർത്ഥനകൾ നിറയ്ക്കുന്നതിന് ഒരു പശ്ചാത്തല ടാസ്ക് ആനുകാലികമായി സെമാഫോർ റിലീസ് ചെയ്യാൻ കഴിയും, ഇത് ഫലപ്രദമായി നിരക്ക് പരിമിതപ്പെടുത്തൽ നടപ്പിലാക്കുന്നു. ആഗോളതലത്തിലുള്ള നിരവധി ക്ലൗഡ് സേവനങ്ങളിലും മൈക്രോസർവീസ് ആർക്കിടെക്ചറുകളിലും ഉപയോഗിക്കുന്ന ഒരു സാധാരണ സാങ്കേതികതയാണിത്.
Asyncio ഇവന്റുകൾ
ഒരു asyncio.Event
എന്നത് ഒരു പ്രത്യേക ഇവന്റ് സംഭവിക്കുന്നതിനായി കോറൂട്ടിനുകളെ കാത്തിരിക്കാൻ അനുവദിക്കുന്ന ഒരു ലളിതമായ സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവ് ആണ്. ഇതിന് രണ്ട് അവസ്ഥകളുണ്ട്: സജ്ജമാക്കിയതും സജ്ജമാക്കാത്തതും. കോറൂട്ടിനുകൾക്ക് ഇവന്റ് സജ്ജമാക്കുന്നതിനായി കാത്തിരിക്കാനും ഇവന്റ് സജ്ജമാക്കാനും അല്ലെങ്കിൽ മായ്ക്കാനും കഴിയും.
ഇവന്റുകൾ എങ്ങനെ പ്രവർത്തിക്കുന്നു
ഒരു ഇവന്റ് സജ്ജമാക്കാത്ത അവസ്ഥയിലാണ് ആരംഭിക്കുന്നത്. ഇവന്റ് സജ്ജമാക്കുന്നതുവരെ എക്സിക്യൂഷൻ താൽക്കാലികമായി നിർത്തിവയ്ക്കാൻ കോറൂട്ടിനുകൾക്ക് wait()
എന്ന് വിളിക്കാം. മറ്റൊരു കോറൂട്ടിൻ set()
എന്ന് വിളിക്കുമ്പോൾ, കാത്തിരിക്കുന്ന എല്ലാ കോറൂട്ടിനുകളും ഉണർത്തുകയും മുന്നോട്ട് പോകാൻ അനുവദിക്കുകയും ചെയ്യുന്നു. clear()
രീതി ഇവന്റിനെ സജ്ജമാക്കാത്ത അവസ്ഥയിലേക്ക് പുനഃസജ്ജമാക്കുന്നു.
Asyncio ഇവന്റുകൾ ഉപയോഗിക്കുന്നു
ഒരു asyncio.Event
ഉപയോഗിക്കുന്നതിനുള്ള ഒരു ഉദാഹരണം ഇതാ:
import asyncio
async def waiter(event, waiter_id):
print(f"Waiter {waiter_id} waiting for event...")
await event.wait()
print(f"Waiter {waiter_id} received event!")
async def main():
event = asyncio.Event()
tasks = [waiter(event, i) for i in range(3)]
await asyncio.sleep(1)
print("Setting event...")
event.set()
await asyncio.gather(*tasks)
if __name__ == "__main__":
asyncio.run(main())
ഈ ഉദാഹരണത്തിൽ, മൂന്ന് വെയ്റ്റർമാരെ സൃഷ്ടിക്കുകയും ഇവന്റ് സജ്ജമാക്കുന്നതിനായി കാത്തിരിക്കുകയും ചെയ്യുന്നു. 1 സെക്കൻഡിനു ശേഷം, പ്രധാന കോറൂട്ടിൻ ഇവന്റ് സജ്ജമാക്കുന്നു. തുടർന്ന് കാത്തിരിക്കുന്ന എല്ലാ കോറൂട്ടിനുകളും ഉണർത്തുകയും മുന്നോട്ട് പോകുകയും ചെയ്യുന്നു.
ഇവന്റ് രീതികൾ
wait()
: ഇവന്റ് സജ്ജമാക്കുന്നതുവരെ എക്സിക്യൂഷൻ താൽക്കാലികമായി നിർത്തിവയ്ക്കുന്നു. ഇവന്റ് സജ്ജമാക്കിയാൽTrue
നൽകുന്നു.set()
: ഇവന്റ് സജ്ജമാക്കുന്നു, കാത്തിരിക്കുന്ന എല്ലാ കോറൂട്ടിനുകളെയും ഉണർത്തുന്നു.clear()
: ഇവന്റിനെ സജ്ജമാക്കാത്ത അവസ്ഥയിലേക്ക് പുനഃസജ്ജമാക്കുന്നു.is_set()
: ഇവന്റ് നിലവിൽ സജ്ജമാണെങ്കിൽTrue
നൽകുന്നു, അല്ലെങ്കിൽFalse
.
പ്രായോഗിക ഇവന്റ് ഉദാഹരണം: അസിൻക്രണസ് ടാസ്ക് പൂർത്തീകരണം
ഒരു അസിൻക്രണസ് ടാസ്ക് പൂർത്തിയാകുമ്പോൾ സൂചിപ്പിക്കാൻ ഇവന്റുകൾ പലപ്പോഴും ഉപയോഗിക്കുന്നു. ഒരു പശ്ചാത്തല ടാസ്ക് പൂർത്തിയാകുന്നതുവരെ ഒരു പ്രധാന കോറൂട്ടിന് കാത്തിരിക്കേണ്ട ഒരു സാഹചര്യം സങ്കൽപ്പിക്കുക. പശ്ചാത്തല ടാസ്ക് പൂർത്തിയാകുമ്പോൾ, പ്രധാന കോറൂട്ടിന് തുടരാമെന്ന് സൂചിപ്പിച്ച് ഒരു ഇവന്റ് സജ്ജമാക്കാൻ കഴിയും.
ഒന്നിലധികം ഘട്ടങ്ങൾ തുടർച്ചയായി നടപ്പിലാക്കേണ്ട ഒരു ഡാറ്റാ പ്രോസസ്സിംഗ് പൈപ്പ്ലൈൻ പരിഗണിക്കുക. ഓരോ ഘട്ടവും ഒരു പ്രത്യേക കോറൂട്ടിനായി നടപ്പിലാക്കാൻ കഴിയും, കൂടാതെ ഓരോ ഘട്ടത്തിൻ്റെയും പൂർത്തീകരണം സൂചിപ്പിക്കാൻ ഒരു ഇവന്റ് ഉപയോഗിക്കാം. അടുത്ത ഘട്ടം അതിൻ്റെ എക്സിക്യൂഷൻ ആരംഭിക്കുന്നതിന് മുമ്പ് മുമ്പത്തെ ഘട്ടത്തിൻ്റെ ഇവന്റ് സജ്ജമാക്കുന്നതിനായി കാത്തിരിക്കുന്നു. ഇത് ഒരു മോഡുലാർ, അസിൻക്രണസ് ഡാറ്റാ പ്രോസസ്സിംഗ് പൈപ്പ്ലൈൻ അനുവദിക്കുന്നു. ഡാറ്റാ എഞ്ചിനീയർമാർ ലോകമെമ്പാടും ഉപയോഗിക്കുന്ന ETL (Extract, Transform, Load) പ്രക്രിയകളിൽ ഈ പാറ്റേണുകൾ വളരെ പ്രധാനമാണ്.
ശരിയായ സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവ് തിരഞ്ഞെടുക്കുന്നു
ഏത് സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവാണ് തിരഞ്ഞെടുക്കേണ്ടത് എന്നത് നിങ്ങളുടെ ആപ്ലിക്കേഷന്റെ പ്രത്യേക ആവശ്യകതകളെ ആശ്രയിച്ചിരിക്കുന്നു:
- ലോക്കുകൾ: പങ്കിട്ട ഒരു ഉറവിടത്തിലേക്ക് എക്സ്ക്ലൂസീവ് ആക്സസ് ഉറപ്പാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുമ്പോൾ ലോക്കുകൾ ഉപയോഗിക്കുക, ഒരു സമയം ഒരു കോറൂട്ടിന് മാത്രമേ അത് ആക്സസ് ചെയ്യാൻ കഴിയൂ. പങ്കിട്ട അവസ്ഥ പരിഷ്കരിക്കുന്ന കോഡിന്റെ നിർണായക ഭാഗങ്ങൾ പരിരക്ഷിക്കുന്നതിന് അവ അനുയോജ്യമാണ്.
- സെമാഫോറുകൾ: ഒരു ഉറവിടത്തിലേക്കുള്ള കൺകറന്റ് ആക്സസുകളുടെ എണ്ണം പരിമിതപ്പെടുത്താനോ നിരക്ക് പരിമിതപ്പെടുത്തൽ നടപ്പിലാക്കാനോ നിങ്ങൾ ആഗ്രഹിക്കുമ്പോൾ സെമാഫോറുകൾ ഉപയോഗിക്കുക. ഉറവിട ഉപയോഗം നിയന്ത്രിക്കുന്നതിനും ഓവർലോഡ് തടയുന്നതിനും അവ ഉപയോഗപ്രദമാണ്.
- ഇവന്റുകൾ: ഒരു പ്രത്യേക ഇവന്റ് സംഭവിക്കുന്നത് സൂചിപ്പിക്കുകയും ആ ഇവന്റിനായി കാത്തിരിക്കാൻ ഒന്നിലധികം കോറൂട്ടിനുകളെ അനുവദിക്കുകയും ചെയ്യുമ്പോൾ ഇവന്റുകൾ ഉപയോഗിക്കുക. അസിൻക്രണസ് ടാസ്ക്കുകൾ ഏകോപിപ്പിക്കുന്നതിനും ടാസ്ക് പൂർത്തീകരണം സൂചിപ്പിക്കുന്നതിനും അവ അനുയോജ്യമാണ്.
ഒന്നിലധികം സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവുകൾ ഉപയോഗിക്കുമ്പോൾ ഡെഡ്ലോക്കുകൾക്കുള്ള സാധ്യതയും പരിഗണിക്കേണ്ടത് പ്രധാനമാണ്. രണ്ട് കോറൂട്ടിനുകളോ അതിലധികമോ ഉറവിടം റിലീസ് ചെയ്യുന്നതിനായി പരസ്പരം കാത്തിരുന്ന് നിശ്ചിതമായി ബ്ലോക്ക് ചെയ്യപ്പെടുമ്പോഴാണ് ഡെഡ്ലോക്കുകൾ സംഭവിക്കുന്നത്. ഡെഡ്ലോക്കുകൾ ഒഴിവാക്കാൻ, ലോക്കുകളും സെമാഫോറുകളും സ്ഥിരമായ ക്രമത്തിൽ നേടുകയും ദീർഘനേരം കൈവശം വയ്ക്കുന്നത് ഒഴിവാക്കുകയും ചെയ്യേണ്ടത് നിർണായകമാണ്.
വിപുലമായ സിൻക്രണൈസേഷൻ ടെക്നിക്കുകൾ
അടിസ്ഥാന സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവുകൾക്ക് പുറമേ, കൺകറൻസി കൈകാര്യം ചെയ്യുന്നതിനുള്ള കൂടുതൽ വിപുലമായ ടെക്നിക്കുകൾ asyncio
നൽകുന്നു:
- ക്യൂകൾ: കോറൂട്ടിനുകൾക്കിടയിൽ ഡാറ്റ കൈമാറുന്നതിന്
asyncio.Queue
ഒരു ത്രെഡ്-സുരക്ഷിതവും കോറൂട്ടിൻ-സുരക്ഷിതവുമായ ക്യൂ നൽകുന്നു. നിർമ്മാതാവ്-ഉപഭോക്താവ് പാറ്റേണുകൾ നടപ്പിലാക്കുന്നതിനും അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകൾ കൈകാര്യം ചെയ്യുന്നതിനും ഇത് ശക്തമായ ഉപകരണമാണ്. - കണ്ടീഷനുകൾ: മുന്നോട്ട് പോകുന്നതിന് മുമ്പ് പ്രത്യേക നിബന്ധനകൾ പാലിക്കുന്നതിനായി കാത്തിരിക്കാൻ
asyncio.Condition
കോറൂട്ടിനുകളെ അനുവദിക്കുന്നു. ഇത് ഒരു ലോക്കിന്റെയും ഇവൻ്റിൻ്റെയും പ്രവർത്തനം സംയോജിപ്പിച്ച് കൂടുതൽ ഫ്ലെക്സിബിളായ സിൻക്രണൈസേഷൻ മെക്കാനിസം നൽകുന്നു.
Asyncio സിൻക്രണൈസേഷനുള്ള മികച്ച രീതികൾ
asyncio
സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവുകൾ ഉപയോഗിക്കുമ്പോൾ പിന്തുടരേണ്ട ചില മികച്ച രീതികൾ ഇതാ:
- നിർണായക വിഭാഗങ്ങൾ കുറയ്ക്കുക: തർക്കം കുറയ്ക്കുന്നതിനും പ്രകടനം മെച്ചപ്പെടുത്തുന്നതിനും നിർണായക വിഭാഗങ്ങളിലെ കോഡ് കഴിയുന്നത്രയും ചെറുതാക്കുക.
- കോൺടെക്സ്റ്റ് മാനേജർമാർ ഉപയോഗിക്കുക: ലോക്കുകളും സെമാഫോറുകളും സ്വയമേവ നേടുന്നതിനും റിലീസ് ചെയ്യുന്നതിനും
async with
സ്റ്റേറ്റ്മെന്റുകൾ ഉപയോഗിക്കുക, എക്സെപ്ഷനുകൾ സംഭവിച്ചാലും അവ എപ്പോഴും റിലീസ് ചെയ്യപ്പെടുന്നുവെന്ന് ഉറപ്പാക്കുക. - തടസ്സപ്പെടുത്തുന്ന പ്രവർത്തനങ്ങൾ ഒഴിവാക്കുക: നിർണായക വിഭാഗത്തിനുള്ളിൽ ഒരിക്കലും തടസ്സപ്പെടുത്തുന്ന പ്രവർത്തനങ്ങൾ നടത്തരുത്. തടസ്സപ്പെടുത്തുന്ന പ്രവർത്തനങ്ങൾ മറ്റ് കോറൂട്ടിനുകളെ ലോക്ക് നേടുന്നതിൽ നിന്ന് തടയുകയും പ്രകടനത്തെ തളർത്തുകയും ചെയ്യും.
- ടൈംഔട്ടുകൾ പരിഗണിക്കുക: പിശകുകൾ അല്ലെങ്കിൽ ഉറവിട ലഭ്യതക്കുറവ് എന്നിവ ഉണ്ടായാൽ നിശ്ചിതമല്ലാത്ത ബ്ലോക്കിംഗ് തടയുന്നതിന് ലോക്കുകളും സെമാഫോറുകളും നേടുമ്പോൾ ടൈംഔട്ടുകൾ ഉപയോഗിക്കുക.
- കൃത്യമായി പരീക്ഷിക്കുക: നിങ്ങളുടെ അസിൻക്രണസ് കോഡ് റേസ് കണ്ടീഷനുകളിൽ നിന്നും ഡെഡ്ലോക്കുകളിൽ നിന്നും മുക്തമാണെന്ന് ഉറപ്പാക്കാൻ അത് കൃത്യമായി പരീക്ഷിക്കുക. റിയലിസ്റ്റിക് വർക്ക്ലോഡുകൾ അനുകരിക്കുന്നതിനും സാധ്യമായ പ്രശ്നങ്ങൾ തിരിച്ചറിയുന്നതിനും കൺകറൻസി ടെസ്റ്റിംഗ് ടൂളുകൾ ഉപയോഗിക്കുക.
ഉപസംഹാരം
Python-ൽ ശക്തവും കാര്യക്ഷമവുമായ അസിൻക്രണസ് ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കുന്നതിന് asyncio
സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവുകളിൽ പ്രാവീണ്യം നേടേണ്ടത് അത്യാവശ്യമാണ്. ലോക്കുകൾ, സെമാഫോറുകൾ, ഇവന്റുകൾ എന്നിവയുടെ ഉദ്ദേശ്യവും ഉപയോഗവും മനസ്സിലാക്കുന്നതിലൂടെ, നിങ്ങൾക്ക് പങ്കിട്ട ഉറവിടങ്ങളിലേക്കുള്ള ആക്സസ് ഫലപ്രദമായി ഏകോപിപ്പിക്കാനും റേസ് കണ്ടീഷനുകൾ തടയാനും നിങ്ങളുടെ കൺകറന്റ് പ്രോഗ്രാമുകളിൽ ഡാറ്റാ സമഗ്രത ഉറപ്പാക്കാനും കഴിയും. നിങ്ങളുടെ പ്രത്യേക ആവശ്യങ്ങൾക്ക് ശരിയായ സിൻക്രണൈസേഷൻ പ്രിമിറ്റീവ് തിരഞ്ഞെടുക്കാനും മികച്ച രീതികൾ പിന്തുടരാനും സാധാരണ അപകടങ്ങൾ ഒഴിവാക്കാൻ നിങ്ങളുടെ കോഡ് കൃത്യമായി പരീക്ഷിക്കാനും ഓർമ്മിക്കുക. അസിൻക്രണസ് പ്രോഗ്രാമിംഗിൻ്റെ ലോകം തുടർച്ചയായി വികസിച്ചുകൊണ്ടിരിക്കുകയാണ്, അതിനാൽ സ്കെയിലബിളും മികച്ച പ്രകടനമുള്ളതുമായ ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കുന്നതിന് ഏറ്റവും പുതിയ സവിശേഷതകളും ടെക്നിക്കുകളും ഉപയോഗിച്ച് അപ്ഡേറ്റ് ആയിരിക്കുന്നത് നിർണായകമാണ്. ആഗോള പ്ലാറ്റ്ഫോമുകൾ കൺകറൻസി എങ്ങനെ കൈകാര്യം ചെയ്യുന്നുവെന്ന് മനസ്സിലാക്കുന്നത് ലോകമെമ്പാടും കാര്യക്ഷമമായി പ്രവർത്തിക്കാൻ കഴിയുന്ന പരിഹാരങ്ങൾ നിർമ്മിക്കുന്നതിന് പ്രധാനമാണ്.